/* Copyright (C) 2008, 2009, 2010 Faindu GmbH, Switzerland.
* All Rights Reserved. The following is Source Code and is subject to all restrictions 
* on such code as contained in the license accompanying this project. */
package blocstac.editimage.crop
{
	import flash.display.Graphics;
	import flash.display.Sprite;
	import flash.events.MouseEvent;
	import flash.geom.Matrix;
	import flash.geom.Point;
	import flash.geom.Rectangle;

public class CropMask extends Sprite
{
	private var _cropTool:CropTool
	private var _visibleWindow:Sprite
	
	private var tlControl:CropControl
	private var trControl:CropControl
	private var blControl:CropControl
	private var brControl:CropControl
	
	private var _imageWidth:Number
	private var _imageHeight:Number
	
	private var _maskX:Number
	private var _maskY:Number
	private var _maskWidth:Number
	private var _maskHeight:Number
	
	private var _updateButtonPosition:Function
	
	public function CropMask(cropTool:CropTool, imageWidth:Number, imageHeight:Number, visibleWindow:Sprite, updateButtonPosition:Function) {
		_cropTool = cropTool
		_imageWidth = imageWidth
		_imageHeight = imageHeight
		_visibleWindow = visibleWindow
		_updateButtonPosition = updateButtonPosition
	}
	
	public function init():void {
		tlControl = new CropControl(CropControl.TOP_LEFT, resizeCropMask)
		tlControl.init()
		_cropTool.addChild(tlControl)
		trControl = new CropControl(CropControl.TOP_RIGHT, resizeCropMask)
		trControl.init()
		_cropTool.addChild(trControl)
		blControl = new CropControl(CropControl.BOTTOM_LEFT, resizeCropMask)
		blControl.init()
		_cropTool.addChild(blControl)
		brControl = new CropControl(CropControl.BOTTOM_RIGHT, resizeCropMask)
		brControl.init()
		_cropTool.addChild(brControl)

		initialSize()		
	}
	
	private function initialSize():void {
		var maskWidth:Number = calculateMaskSize(_imageWidth)
		var maskHeight:Number = calculateMaskSize(_imageHeight)
		var maskX:Number = Math.ceil((_imageWidth-maskWidth)/2)
		var maskY:Number = Math.ceil((_imageHeight-maskHeight)/2)
		updateSizeTo(maskX, maskY, maskWidth, maskHeight)
	}
	
	private function calculateMaskSize(size:Number):Number {
		if (_imageWidth > 140) {
			return 100
		} else {
			return (size > 40) ? size-40 : size
		}
	}
	
	private function resizeCropMask(mouseEvent:MouseEvent, position:int):void {
		var newPoint:Point = new Point(mouseEvent.stageX, mouseEvent.stageY)
		var stageToCropMask:Matrix = transform.concatenatedMatrix
		stageToCropMask.invert()
		var localPoint:Point = stageToCropMask.transformPoint(newPoint)
		switch (position) {
			case CropControl.TOP_LEFT:
				updateSizeTo(localPoint.x, localPoint.y, _maskX+_maskWidth-localPoint.x, _maskY+_maskHeight-localPoint.y); break

			case CropControl.TOP_RIGHT:
				updateSizeTo(_maskX, localPoint.y, localPoint.x-_maskX, _maskY+_maskHeight-localPoint.y); break

			case CropControl.BOTTOM_LEFT:
				updateSizeTo(localPoint.x, _maskY, _maskX+_maskWidth-localPoint.x, localPoint.y-_maskY); break

			case CropControl.BOTTOM_RIGHT:
				updateSizeTo(_maskX, _maskY, localPoint.x-_maskX, localPoint.y-_maskY); break
		}
		_updateButtonPosition()
	}
	
	private function updateSizeTo(x:Number, y:Number, width:Number, height:Number):void {
		
		if (x < 0) {
			width += x
			x = 0
		} else if (_imageWidth < x) {
			x = _imageWidth
		}
		if (y < 0) {
			height += y
			y = 0
		} else if (_imageHeight < y) {
			y = _imageHeight
		}
		if (width < 2) {
			return
		}
		if (x + width > _imageWidth) {
			width = _imageWidth-x
		}
		if (height < 2) {
			return
		}
		if (y + height > _imageHeight) {
			height = _imageHeight-y
		}
		
		// mask
		var gm:Graphics = graphics
		gm.clear()
		gm.beginFill(0xFF0000)
		gm.drawRect(-_imageWidth, -_imageHeight, _imageWidth+x, 3*_imageHeight)
		gm.drawRect(x-1, -_imageHeight, width+2, _imageHeight+y)
		gm.drawRect(x+width, -_imageHeight, _imageWidth+_imageWidth-width-x, 3*_imageHeight)
		gm.drawRect(x-1, y+height, width+2, _imageHeight+_imageHeight-height-y)
		gm.endFill()
		
		// grey background
		var g:Graphics = _cropTool.graphics
		g.clear()
		g.beginFill(0xcccccc, 0.85)
		g.drawRect(0, 0, _imageWidth, _imageHeight)
		g.endFill()
		
		// frame of grey background
		g.lineStyle(1, 0x333333)
		g.moveTo(x-1, y-1)
		g.lineTo(x+width, y-1)
		g.lineTo(x+width, y+height)
		g.lineTo(x-1, y+height)
		g.lineTo(x-1, y-1)
		
		tlControl.x = x-CropControl.CONTROL_HALF_SIZE
		tlControl.y = y-CropControl.CONTROL_HALF_SIZE-0.5
		trControl.x = x+width+CropControl.CONTROL_HALF_SIZE
		trControl.y = y-CropControl.CONTROL_HALF_SIZE-0.5
		blControl.x = x-CropControl.CONTROL_HALF_SIZE
		blControl.y = y+height+CropControl.CONTROL_HALF_SIZE
		brControl.x = x+width+CropControl.CONTROL_HALF_SIZE
		brControl.y = y+height+CropControl.CONTROL_HALF_SIZE
		
		var gv:Graphics = _visibleWindow.graphics
		gv.clear()
		gv.beginFill(0x00ff00, 0)
		gv.drawRect(x, y, width, height)
		gv.endFill()
		
		_maskX = x
		_maskY = y
		_maskWidth = width
		_maskHeight = height
	}

	//--------------------------------------------------------------------------
	//
	//  Drag & Drop
	//
	//--------------------------------------------------------------------------	
	private var _lastMoveX:Number
	private var _lastMoveY:Number
	
	public function initMaskMove(lastMoveX:Number, lastMoveY:Number):void {
		_lastMoveX = lastMoveX
		_lastMoveY = lastMoveY
	}
	
	public function moveRelative(moveX:Number, moveY:Number):void {
		var relativeMoveX:Number = moveX-_lastMoveX
		var relativeMoveY:Number = moveY-_lastMoveY
		var newX:Number = _maskX+relativeMoveX
		var newY:Number = _maskY+relativeMoveY
		var maskOverTop:Boolean = newY < 0
		var maskOverRight:Boolean = newX+_maskWidth > _imageWidth
		var maskOverBottom:Boolean = newY+_maskHeight > _imageHeight
		var maskOverLeft:Boolean = newX < 0
		if (maskOverRight || maskOverLeft) {
			newX = _maskX
		}
		if (maskOverTop || maskOverBottom) {
			newY = _maskY
		}
		
		updateSizeTo(newX, newY, _maskWidth, _maskHeight)
		_lastMoveX = moveX
		_lastMoveY = moveY
		
		_updateButtonPosition()
	}

	//--------------------------------------------------------------------------
	//
	//  Methods
	//
	//--------------------------------------------------------------------------	
	public function getMask():Rectangle {
		return new Rectangle(_maskX, _maskY, _maskWidth, _maskHeight)
	}
	
	public function dispose():void {
		graphics.clear()
		_cropTool.graphics.clear()
		_visibleWindow.graphics.clear()
		
		_cropTool.removeChild(tlControl)
		tlControl.dispose()
		tlControl = null
		_cropTool.removeChild(trControl)
		trControl.dispose()
		trControl = null
		_cropTool.removeChild(blControl)
		blControl.dispose()
		blControl = null
		_cropTool.removeChild(brControl)
		brControl.dispose()
		brControl = null
	}
	
}
}